using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using OpenComposite.Base.Designer;
using OpenComposite.EII.Designer.Generic;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.Repository;
using WeifenLuo.WinFormsUI.Docking;
using OpenComposite.Base.Collections;

namespace OpenComposite.EII.Designer.SCA
{
	public class ExposedCapabilitySymbol : Symbol, IConnectorFactory//, IRepositoryItemSymbol
	{
		#region Initialization
		public ExposedCapabilitySymbol()
		{
			init();
		}
		private void init()
		{
			this.BeginUpdate();

			//_connectorInterface = null;

			this.Border = BorderType.CustomPolygon;//BorderType.SimpleArrowRight;
			this.BorderColor = Color.Black;
			this.BorderWidth = 2;

			this.BackColor = Color.FromArgb(160, 60, 160);
			this.BackColor2 = Color.FromArgb(250, 200, 250);
			this.BackLinearGradientMode = LinearGradientMode.ForwardDiagonal;
			this.BackBrushMode = BackgroundBrushMode.LinearGradient;

			this.Size = new Size(100, 50);
			this.MinimumSize = new Size(70, 50);

			//this.Name = "exportSymbol" + GetCount(typeof(InterfaceSymbol));
			this.NameTextBox.AutoSize = false;
			this.NameTextBox.Bounds = this.ClientRectangle;
            this.NameTextBox.ReadOnly = true;
			this.Text = "Service";
			this.TextAlign = ContentAlignment.MiddleCenter;

			this.ReadOnly = false;

			//
			// this.ContextMenuStrip
			//
			this.ContextMenuStrip = new ContextMenuStrip();
			this.ContextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(ContextMenuStrip_Opening);
			this.ContextMenuStrip.Items.Add("Edit Capabilities...", null, new EventHandler(context_EditCapabilityMethods));
			//this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
			//this.ContextMenuStrip.Items.Add("Remove Capability", null, new EventHandler(context_Remove));

			_svcModule = null;
			_verbs = null;
			_isCollapsed = false;

			_frmVerbs = null;

			this.EndUpdate();
		}

		#endregion

		#region Public Members

		#region Properties
		public ServiceModule ServiceModule
		{
			get { return _svcModule; }
			set
			{
				_svcModule = value;
				if ( _svcModule != null ) {
					this.Text = _svcModule.Name;
				}
			}
		}
		public BindingListEx<Verb> Verbs
		{
			get
			{
				if ( _svcModule != null && _verbs == null ) {
					return _svcModule.GetVerbs();
				} else {
					return _verbs;
				}
			}
			set { _verbs = value; }
		}
		public bool ReadOnly { get; set; }
		#endregion

		#region Events
		public event EventHandler VerbsChanged = null;
		#endregion

		#region Methods
		public void Expand()
		{
			_isCollapsed = false;
			this.MinimumSize = new Size(100, 50);
			this.Size = new Size(100, 50);
			this.NameTextBox.Visible = true;
			this.NameTextBox.AutoSize = false;
			this.NameTextBox.Bounds = this.ClientRectangle;
		}
		public void Collapse()
		{
			_isCollapsed = true;
			this.MinimumSize = new Size(25, 15);
			this.Size = new Size(25, 15);
			this.NameTextBox.Visible = false;
		}
		#endregion

		#region Overrides
		public override bool UseGrid
		{
			get
			{
				return false;//!_isCollapsed;
			}
		}
		public override bool NoClip
		{
			get
			{
				return true;
			}
		}
		public override bool CanMove
		{
			get
			{
				return false;
			}
		}
		public override bool CanResize
		{
			get
			{
				return false;
			}
		}

		public override object GetDragObject(Point location, MouseButtons button)
		{
			return this;
		}
		public override void DropObject(object obj, Point location, MouseButtons button)
		{
			if ( this.IsDropAllowed(obj, location, button) ) {
				if ( button == MouseButtons.Right ) {
					DesignerControl dctrl = obj as DesignerControl;
					if ( obj is ReferenceSymbol ) {
						this.DesignerViewControl.AddRoute((DesignerControl)obj, this);
					} else if ( obj is InterfaceSymbol ) {
						if ( dctrl.Parent is ServiceComponentSymbol )
							this.DesignerViewControl.AddRoute(this, (DesignerControl)obj);
						else if ( dctrl.Parent is ServiceModuleSymbol ) {
							if ( dctrl.Parent.Parent == this.Parent )
								this.DesignerViewControl.AddRoute(this, (DesignerControl)obj);
							else
								this.DesignerViewControl.AddRoute((DesignerControl)obj, this);
						} else if ( dctrl.Parent.Parent == this.Parent ) {
							this.DesignerViewControl.AddRoute(this, (DesignerControl)obj);
						}
					} else if ( obj is ExternalSymbol ) {
						this.DesignerViewControl.AddRoute((DesignerControl)obj, this);
					}
				}
			}
		}
		public override bool IsDropAllowed(object obj, Point location, MouseButtons button)
		{
			if ( button == MouseButtons.Right ) {
				DesignerControl dctrl = obj as DesignerControl;
				if ( obj is ReferenceSymbol ) {
					if ( dctrl.Parent is ServiceComponentSymbol )
						return ( this.Parent is ServiceComponentSymbol &&
								 dctrl.Parent.Parent == this.Parent.Parent );
					else if ( dctrl.Parent is ServiceModuleSymbol )
						return ( this.Parent is ServiceModuleSymbol &&
								 dctrl.Parent != this.Parent );
					else
						return false;
				} else if ( obj is InterfaceSymbol ) {
					if ( dctrl.Parent is ServiceComponentSymbol )
						return ( ( this.Parent is ServiceModuleSymbol || this.Parent is SOBASymbol ) &&
								 dctrl.Parent.Parent == this.Parent );
					else if ( dctrl.Parent is ServiceModuleSymbol ) {
						if ( this.Parent is ServiceComponentSymbol )
							return ( dctrl.Parent == this.Parent.Parent );
						else if ( this.Parent is ServiceModuleSymbol )
							return ( dctrl.Parent != this.Parent );
						else
							return false;
					} else
						return ( dctrl.Parent.Parent == this.Parent );
				} else {
					return ( obj is ExternalSymbol );
				}
			} else {
				return IsDropAllowed(obj.GetType(), location, button);
			}
		}
		public override bool IsDropAllowed(Type type, Point location, MouseButtons button)
		{
			return ( button == MouseButtons.Right &&
				( type == typeof(ReferenceSymbol) || type == typeof(ExternalSymbol) ||
				  type == typeof(InterfaceSymbol) ) );
		}

		public override Point GetRouteStart(RouteDockDirection dock, Route route)
		{
			Point pt = base.GetRouteStart(dock, route);
			return pt;
		}
		public override Point GetRouteEnd(RouteDockDirection dock, Route route)
		{
			Point pt = base.GetRouteEnd(dock, route);
			return pt;
		}

		public override bool CreateRouteStart(DesignerControl controlEnd,
			out IConnector connector, out LineCap cap, out CustomLineCap customcap,
			out RouteDockDirection dockStart, out RouteDockDirection dockEnd,
			out bool useStartConnectorAsRouteStart)
		{
			bool ok = base.CreateRouteStart(controlEnd, out connector, out cap, out customcap, out dockStart, out dockEnd, out useStartConnectorAsRouteStart);
			if ( controlEnd is InterfaceSymbol &&
					( controlEnd.Parent is ServiceComponentSymbol ||
					  ( controlEnd.Parent.Parent == this.Parent ) ) ) {
				//addConnectedInterface((InterfaceSymbol)controlEnd);
			}
			//if ( _connectorInterface == null && (controlEnd is ImportSymbol || controlEnd is ExternalSymbol) ) {
			//    _connectorInterface = new InterfaceConnectorSymbol();
			//    _connectorInterface.Location = new Point(-(int)( _connectorInterface.Width / 2 ) - 5, (int)( this.ClientRectangle.Height / 2 ) - ( _connectorInterface.Height ) + 2);
			//    _connectorInterface.Anchor = System.Windows.Forms.AnchorStyles.Left;
			//    this.Controls.Add(_connectorInterface);
			//}
			if ( controlEnd is ReferenceSymbol ) {
				dockEnd = RouteDockDirection.Right;
				dockStart = RouteDockDirection.Left;
				//connector = _connectorInterface;
				//cap = LineCap.RoundAnchor;
				customcap = null;
			} else {
				dockEnd = RouteDockDirection.Left;
				dockStart = RouteDockDirection.Right;
				//cap = LineCap.RoundAnchor;
				customcap = null;
			}
			return ok;
		}
		public override bool CreateRouteEnd(DesignerControl controlStart,
			out IConnector connector, out LineCap cap, out CustomLineCap customcap,
			out RouteDockDirection dockStart, out RouteDockDirection dockEnd,
			out bool useEndConnectorAsRouteEnd)
		{
			bool ok = base.CreateRouteEnd(controlStart, out connector, out cap, out customcap, out dockStart, out dockEnd, out useEndConnectorAsRouteEnd);

			//if ( _connectorInterface == null ) {
			//    _connectorInterface = new InterfaceConnectorSymbol();
			//    _connectorInterface.Location = new Point(-(int)( _connectorInterface.Width / 2 ) - 5, (int)( this.ClientRectangle.Height / 2 ) - ( _connectorInterface.Height ) + 4);
			//    _connectorInterface.Anchor = System.Windows.Forms.AnchorStyles.Left;
			//    this.Controls.Add(_connectorInterface);
			//}
			//connector = _connectorInterface;
			if ( controlStart is ExternalSymbol ) {
				cap = LineCap.Custom;
				customcap = new AdjustableArrowCap(7.0f, 10.0f, false);
			} else {
				dockEnd = RouteDockDirection.Left;
				dockStart = RouteDockDirection.Right;
				//cap = LineCap.RoundAnchor;
				customcap = null;
			}
			return ok;
		}

		public override void ReadXml(System.Xml.XmlReader reader)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
			try {
				while ( reader.Read() ) {
					switch ( reader.Name ) {
						case "DesignerControl":
							if ( reader.NodeType == System.Xml.XmlNodeType.EndElement ) return;
							break;
						case "IsCollapsed":
							bool.TryParse(reader.ReadString(), out _isCollapsed);
							if ( _isCollapsed ) Collapse();
							break;
						//case "Capability":
						//    if ( reader.MoveToAttribute("id") && reader.ReadAttributeValue() ) {
						//        _svcModule = repSvc.GetItem<Capability>(int.Parse(reader.Value));
						//    }
						//    if ( reader.MoveToAttribute("isRef") && reader.ReadAttributeValue() ) {
						//        this.IsReference = (bool)bc.ConvertFromString(reader.Value);
						//    }
						//    break;
						default:
							ReadStandardProperties(reader);
							break;
					}
				}
			} finally {
			}
		}
		public override void WriteXml(System.Xml.XmlWriter writer)
		{
			System.ComponentModel.BooleanConverter bc = new System.ComponentModel.BooleanConverter();
			WriteStandardProperties(writer);

			writer.WriteElementString("IsCollapsed", _isCollapsed.ToString());

			//if ( _svcModule != null ) {
			//    writer.WriteStartElement("Capability");
			//    writer.WriteAttributeString("id", _svcModule.ID.ToString());
			//    writer.WriteAttributeString("name", _svcModule.Name);
			//    writer.WriteAttributeString("isRef", bc.ConvertToString(this.IsReference));
			//    writer.WriteEndElement();
			//}
		}

		public override object GetService(Type serviceType)
		{
			if ( _svcModule != null )
				return _svcModule.GetService(serviceType);
			else
				return base.GetService(serviceType);
		}

		public override void Paint(PaintEventArgs pe)
		{
			base.Paint(pe);
			Rectangle paintBound = this.GetPaintBounds();
			if ( this.Verbs != null && this.Verbs.Count > 1 ) {
				// diameter/radius of the exposed capability symbol
				int d = (int)( paintBound.Width * .2f ), r = (int)( d * .5f );
				Rectangle rect = new Rectangle(paintBound.X, paintBound.Y + (int)( paintBound.Height * .5f ) - r, d, d);
				rect.Inflate(-3, -3);
				pe.Graphics.DrawEllipse(this.BorderPen, rect);
			}
		}

        protected override void OnRemoved(EventArgs e)
        {
            base.OnRemoved(e);
        }

        protected override void OnRemoving(System.ComponentModel.CancelEventArgs e)
        {
            base.OnRemoving(e);
        }
		#endregion

		#endregion

		#region Protected Members

		#region Overrides
		protected override void CalculateBorder(int width, int height, ref GraphicsPath path)
		{
			//   _________ ____y1__
			//   \        \       ^
			//    \        \      |
			// O---)        )--y2 |h
			// |  /|       /|     |
			// | /_|______/_|__y3_v
			// | | |      | |
			//x1 x2 x3    x4 x5
			// |<-----w---->|
			int x1 = 0;
			int x2 = (int)( width * .2f );
			int x3 = x2 * 2;
			int x4 = (int)( width * .8f );
			int x5 = width;
			int y1 = 0;
			int y2 = (int)( height * .5f );
			int y3 = height;
			// diameter/radius of the exposed capability symbol
			int d = (int)( width * .2f ), r = (int)( d * .5f );
			path.AddPolygon(
				new Point[] {
					new Point(x2,y1),
					new Point(x4,y1),
					new Point(x5,y2),
					new Point(x4,y3),
					new Point(x2,y3),
					new Point(x3,y2)
				}
			);
			path.AddEllipse(x1, y2 - r, d, d);
			path.AddLine(x1 + d, y2, y3, y2);
		}
		protected override Rectangle CalculateClientArea()
		{
			//   _________ ____y1__
			//   \        \       ^
			//    \ cacaca \      |
			// O---)cacaca  )--y2 |h
			// |  /|cacaca /|     |
			// | /_|______/_|__y3_v
			// | | |      | |
			//x1 x2 x3    x4 x5
			// |<-----w---->|
			Rectangle rc = this.Bounds;
			//int x1 = 0;
			int x2 = (int)( rc.Width * .2f );
			int x3 = x2 * 2;
			int x4 = (int)( rc.Width * .8f );
			int x5 = rc.Width;
			//int y1 = 0;
			int y2 = (int)( rc.Height * .5f );
			int y3 = rc.Height;
			//int pad = 5;
			int x = rc.X + x3;
			int w = x4 - x3 + 5;
			int y = rc.Y + (int)( y3 * .25 );
			int h = rc.Height - (int)( y3 * .25 ) * 2;
			return new Rectangle(x, y, w, h);
		}
		protected override void OnVisibleChanged()
		{
			if ( !this._isCollapsed )
				base.OnVisibleChanged();
		}
		#endregion

		#endregion

		#region Private Members

		#region Variables
		//private InterfaceConnectorSymbol _connectorInterface;
		private bool _isCollapsed;
		private ServiceModule _svcModule;
		private BindingListEx<Verb> _verbs;
		private FormShowCapabilities _frmVerbs;
		#endregion

		#region Methods
		private void onVerbsChanged()
		{
			EventHandler tmp = this.VerbsChanged;
			if ( tmp != null )
				tmp(this, EventArgs.Empty);
		}
		#endregion

		#region Event Handlers
		private void ContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if ( this.ReadOnly ) {
				this.ContextMenuStrip.Items[0].Text = "Show Capabilities...";
			} else {
				this.ContextMenuStrip.Items[0].Text = "Edit Capabilities...";
			}
		}
		private void context_EditCapabilityMethods(object sender, EventArgs e)
		{
			if ( _frmVerbs == null ) {
				if ( _svcModule != null ) {
					_frmVerbs = new FormShowCapabilities(_svcModule);
				} else {
					_frmVerbs = new FormShowCapabilities(this, _verbs);
				}
				_frmVerbs.VerbsChanged += new EventHandler(_frmVerbs_VerbsChanged);
			} else {
				_frmVerbs.BringToFront();
				if ( _svcModule != null ) {
					_frmVerbs.ServiceModule = _svcModule;
				} else {
					_frmVerbs.Verbs = _verbs;
				}
				return;
			}
			_frmVerbs.ReadOnly = this.ReadOnly;
			_frmVerbs.FormClosed += new FormClosedEventHandler(frm_FormClosed);
			DockPanel dp = this.GetService(typeof(DockPanel)) as DockPanel;
			IController ictrler = this.DesignerViewControl.DesignController as IController;
			if ( ictrler != null ) {
				ictrler.Closed += new EventHandler(ictrler_Closed);
			}
			if ( dp != null ) {
				Point loc = this.Parent.PointToDesignerView(this.Location);
				loc = this.DesignerViewControl.PointToScreen(loc);
				loc.X -= 50;
				loc.Y += this.Height + 20;
				_frmVerbs.Show(dp, new Rectangle(loc, _frmVerbs.Size));
			} else {
				_frmVerbs.Show();
			}
		}

		void _frmVerbs_VerbsChanged(object sender, EventArgs e)
		{
			onVerbsChanged();
		}

		private void ictrler_Closed(object sender, EventArgs e)
		{
			if ( _frmVerbs != null ) {
				try {
					IController ictrler = sender as IController;
					if ( ictrler != null ) {
						ictrler.Closed -= new EventHandler(ictrler_Closed);
					}
					_frmVerbs.Close();
				} catch {
				} finally {
					_frmVerbs = null;
				}
			}
		}
		private void frm_FormClosed(object sender, FormClosedEventArgs e)
		{
			FormShowCapabilities frm = sender as FormShowCapabilities;
			if ( frm == null )
				return;
			if ( frm.DialogResult == DialogResult.OK && !frm.ReadOnly ) {
				onVerbsChanged();
			}
			frm.FormClosed -= new FormClosedEventHandler(frm_FormClosed);
			frm.VerbsChanged -= new EventHandler(_frmVerbs_VerbsChanged);
			_frmVerbs = null;
			if ( this.DesignerViewControl != null && this.DesignerViewControl.TopLevelControl != null ) {
				this.DesignerViewControl.TopLevelControl.BringToFront();
			}
		}

		private void context_Remove(object sender, EventArgs e)
		{
			this.Remove();
		}
		#endregion

		#endregion

		//#region IRepositoryItemSymbol Members

		//public bool SaveHierarchy
		//{
		//    get { return false; }
		//}

		//private bool _isReference = false;
		//public bool IsReference
		//{
		//    get { return _isReference; }
		//    set { _isReference = value; }
		//}

		//public bool CanBeMainControl
		//{
		//    get { return false; }
		//}

		//public OpenComposite.EII.Repository.IRepositoryItem RepositoryItem
		//{
		//    get
		//    {
		//        return _capability;
		//    }
		//    set
		//    {
		//        _capability = value as Repository.Capability;
		//        if ( _capability != null ) {
		//            _capability.Reload();
		//            if ( _capability.ID > 0 && _capability.Name != Resources.sNewCapability )
		//                this.Text = _capability.Name;
		//            else
		//                _capability.Name = this.Text;
		//        }
		//    }
		//}

		//public void Load(int idRepository, int idDomain)
		//{
		//    RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
		//    if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");

		//    if ( _capability != null ) {
		//        //DataTable dt = Global.Data.GetRepositoryHierarchyChildRepositoryList(_capability, ItemType.Operation);
		//        //_listOperations.Clear();
		//        //foreach ( DataRow row in dt.Rows ) {
		//        //    Operation op = repSvc.GetItem(ItemType.Operation, row) as Operation;
		//        //    if ( op != null ) {
		//        //        _listOperations.Add(op);
		//        //        if ( op.ProcessGuid != Guid.Empty ) {
		//        //            if ( this.Parent is OrchestrationComponentSymbol )
		//        //                ( (OrchestrationComponentSymbol)this.Parent ).ProcessOperation = op;
		//        //        }
		//        //    }
		//        //}
		//    }
		//}
		//public bool Save(int idRepository, int idDomain)
		//{
		//    RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
		//    if ( repSvc == null ) throw new NullReferenceException("RepositoryService not available.");

		//    if ( _capability == null ) {
		//        IRepositoryItem parentItem = null;
		//        _capability = repSvc.GetNewItem<Capability>(false, ref parentItem);
		//        _capability.Name = this.Text;
		//    }

		//    bool ok = _capability.Save();
		//    if ( ok ) {
		//        //Global.Data.DeleteRepositoryChildHierarchy(_capability);
		//        //foreach ( Operation op in this.Operations ) {
		//        //    op.Save();
		//        //    Global.Data.AddRepositoryHierarchy(_capability, op, idRepository);
		//        //}
		//    }
		//    return ok;
		//}

		//public bool Delete(bool bAsk)
		//{
		//    if ( _capability == null )
		//        return true;

		//    return _capability.Delete(bAsk);
		//}

		//protected override void OnTextChanged(EventArgs e)
		//{
		//    if ( _capability != null )
		//        _capability.Name = this.Text;

		//    base.OnTextChanged(e);
		//}
		//private Repository.Capability _capability;


		//#endregion
	}
}
